#ifndef __OPTS__
#define __OPTS__

#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

    enum
    {
        // opt state ...
        OPT_STATE_REQUIRED = 0X1,
        OPT_STATE_NEEDARG = 0X2,
        OPT_STATE_HASDATA = 0X4,
        OPT_STATE_USAGE = 0X8,
        // user state ...
    };
    typedef struct opt_st opt_t;
    typedef struct opts_st opts_t;
#define OPT_INIT(opt, state, set_func, data_deinit_func) {opt, state, NULL, set_func, data_deinit_func}

    typedef void (*opt_data_deinit_impl)(opt_t *opt);
    typedef int (*opt_set_impl)(opts_t *opts, opt_t *opt, const char *arg);
    struct opt_st
    {
        char opt;
        uint16_t state;
        void *data;
        opt_set_impl setter;
        opt_data_deinit_impl data_deinit;
    };

#define OPTS_CHECK_FAIL (0X5B)
#define OPTS_PARSE_ERR_CONTINUE (0X45)
#define OPTS_PARSE_ERR_RETURN (0X43)
    typedef int (*opts_parse_impl)(opts_t *opts, int argc, char *argv[], char *tmpbuf);
    typedef int (*opts_parse_err_impl)(opts_t *opts, opt_t *opt, int parse_err, const char *arg);
    typedef void *(*opts_get_impl)(opts_t *opts, char opt);

    struct opts_st
    {
        opt_t *opt_arr;
        size_t opt_arr_len;
        opts_parse_impl parse;
        opts_parse_err_impl parse_err;
        opts_get_impl getter;
    };

    extern int opts_init(opts_t *opts, opt_t *opt_arr, size_t opt_arr_len, opts_parse_err_impl parse_err);
    extern void opts_deinit(opts_t *opts);
#ifdef __cplusplus
}
#endif

#endif